#!/bin/bash
#
# 实现项目前端代码发布、升级、比对功能：
#
# 发布：
#     用于发布新版本时，生成该版本的文件指纹信息并保存下来随着代码一起提交
#     需要设置参数中tag值
#
# 比对：
#     判断当前工程代码与目标版本的差异，列出文件变化清单，输出到anvil-upgrade-版本号.log文件
#     需要设置：upgrade_tag，来指定升级到的目标版本号
# 
# 升级：
#     在比对的基础上，正对差异进行自动处理，并将处理结果输出到anvil-upgrade-result.log文件
#     处理逻辑：
#     1. 新版本中文件当前项目中不存在，则复制
#     2. 新版本的文件当前项目中存在：
#        2.1 如果当前项目文件未修改，用新版本文件替换，备份当前项目文件到.backup
#        2.2 如果当前项目文件已修改，重名新版版本文件并复制，【需要人工比对处理】
#
#####配置参数####################################

# 升级到目标版本
upgrade_tag=""
# 当前版本（发布时使用该版本）
tag="4.2.4-Release"
# 是否输出校验通过的记录(Y输出  N不输出)
echo_match="N"
#################################################

# 根目录
root=..
# 当前目录
dirs=("$root/public" "$root/scripts" "$root/src" "$root/types")
# dirs=("$root/bin")

# 当前版本文件指纹文件
sha_file=".anvil.$tag.sha256"
# 临时文件目录
upgrade_tmp="$upgrade_tag"
# 升级目标版本代码根目录
upgrade_root="$upgrade_tmp/anvil-basic-ui"
# 升级目标版本代码指纹文件
upgrade_sha_file="$upgrade_root/anvil/.anvil.$upgrade_tag.sha256"
# 日志文件
log_file="anvil-cli.log"
# 升级结果
upgrade_result="anvil-upgrade-result.log"

# 输出日志
log() {
    echo $1
    echo $1 >>$log_file
}
# 输出升级结果
log_result() {
    echo $1 >>$upgrade_result
}
# 遍历文件夹中文件
sum_files() {
    for file in $(ls -a $1); do
        if [ -f $1"/"$file ]; then
            sha256sum $1"/"$file >>$sha_file
        fi
    done
}
# 遍历文件夹
sum_dir() {
    sum_files $1
    for file in $(ls -a $1); do
        if [ -d $1"/"$file ]; then
            if [[ $file != '.' && $file != '..' ]]; then
                sum_dir $1"/"$file
            fi
        fi
    done
}
# 克隆代码
git_clone() {
    if [[ $upgrade_tag == "" ]]; then
        log "升级到目标版本参数不可以为空"
        exit
    fi
    rm -rf $upgrade_tmp
    mkdir -p $upgrade_tmp
    log "开始下载新版本[$upgrade_tag]代码"
    cd $upgrade_tmp
    git clone -b $upgrade_tag "ssh://git@192.168.144.53:10080/anvil-platform/anvil-basic/anvil-basic-ui.git" >>$log_file
    cd ..
    # 检查新版本Hash文件是否存在
    if [[ ! -f $upgrade_sha_file ]]; then
        log "新版本[$upgrade_tag]中指纹文件[$upgrade_sha_file]不存在，不支持自动升级至该版本，请联系平台管理员"
        rm -rf $upgrade_tmp
        exit 1;
    fi
}
# 发布指纹
release() {
    log ">> 开始发布文件指纹..."
    rm $sha_file

    log "   创建根目录下文件指纹..."
    # 当前目录的所有文件
    sum_files $root

    # 遍历指定的文件夹
    for dir in ${dirs[@]}; do
        log "   创建[$dir]目录下文件指纹..."
        sum_dir $dir
    done

    log ">> 成功生成项目文件指纹: $sha_file"
}
# 比对指纹
comparison() {
    log ">> 开始比对文件指纹..."
    git_clone

    log "   比对根目录下文件指纹..."
    # 1.检查新版本的文件是否存在旧版本中，不存在则复制，变更过则重命名复制
    while read line; do
        different=$(echo $line | sha256sum -c --quiet)
        filename=${line:66}
        if [[ $different == '' ]]; then
            if [[ $echo_match == 'Y' ]]; then
                log "【匹配】：$line"
            fi
        elif [[ $different =~ "FAILED open or read" ]]; then
            log "【新增文件】：$filename"
        elif [[ $different =~ "FAILED" ]]; then
            log "【修改文件】：$filename"
        else
            log "【未知错误】：$different"
        fi
    done <$upgrade_sha_file
    # 2.检查当前版本的文件是否存在修改或删除
    while read line; do
        different=$(echo $line | sha256sum -c --quiet)
        filename=${line:66}
        if [[ $different == '' ]]; then
            if [[ $echo_match == 'Y' ]]; then
                log "【匹配】：$line"
            fi
        elif [[ $different =~ "FAILED open or read" ]]; then
            log "【删除文件】：$filename"
        elif [[ $different =~ "FAILED" ]]; then
            log "【修改文件】：$filename"
        else
            log "【未知错误】：$different"
        fi
    done <$sha_file
    log ">> 比对文件指纹完成"
}
# 升级前端文件，比对并进行文件更新
upgrade() {
    log ">> 开始比对文件指纹并进行文件更新..."
    git_clone

    # 1.检查新版本的文件是否存在旧版本中，不存在则复制
    log "   1.检查新版本的文件是否存在旧版本中，不存在则复制..."
    while read line; do
        different=$(echo $line | sha256sum -c --quiet)
        filename=${line:66}
        if [[ $different == '' ]]; then
            if [[ $echo_match == 'Y' ]]; then
                log "【匹配】：$line"
            fi
        elif [[ $different =~ "FAILED open or read" ]]; then
            log "【新增文件】：$filename"
            log_result "【新增文件】$filename"
            cp "$upgrade_root/anvil/$filename" "$root/anvil/$filename"
        elif [[ $different =~ "FAILED" ]]; then
            log "【修改文件】：$filename"
            log_result "【修改文件】$filename.$upgrade_tag"
            cp "$upgrade_root/anvil/$filename" "$root/anvil/$filename.$upgrade_tag"
        else
            log "【未知错误】：$different"
        fi
    done <$upgrade_sha_file

    # 2.检查当前版本的文件是否存在修改或删除
    log "   1.检查当前版本的文件是否存在修改或删除..."
    while read line; do
        different=$(echo $line | sha256sum -c --quiet)
        filename=${line:66}
        if [[ $different == '' ]]; then
            # 本地没有修改过，如果有新版本直接覆盖
            if [[ -f "$root/anvil/$filename.$upgrade_tag" ]]; then
                mv "$root/anvil/$filename" "$root/anvil/$filename.backup"
                mv "$root/anvil/$filename.$upgrade_tag" "$root/anvil/$filename"
                log "【升级文件】$filename"
                log_result "【升级文件】$filename"
            else
                if [[ $echo_match == 'Y' ]]; then
                    log "【未修改】：$line"
                fi
            fi
        elif [[ $different =~ "FAILED open or read" ]]; then
            log "【删除文件】：$filename，不需要处理，如果新版本需要会自动复制"
        elif [[ $different =~ "FAILED" ]]; then
            log "【修改文件】：$filename，不需要处理，有可能是删除的文件，新版本已拷贝，如果是修改的则新版本文件已重命名拷贝"
       else
            log "【未知错误】：$different"
        fi
    done <$sha_file
    log ">> 比对文件指纹并进行文件更新完成"
}
# 清理临时文件
clear() {
    rm -rf $log_file
    rm -rf $upgrade_result
    rm -rf $upgrade_tmp
}
# 校验环境
valid() {
    # 检查当前版本Hash文件是否存在
    if [[ ! -f $sha_file ]]; then
        log "本项目指纹文件[$sha_file]不存在，请从模板工程代码分支[$tag]中下载项目版本指纹文件"
        exit 1;
    fi

    # 检查git命令
    git --version > /dev/null
    if [[ $? != 0 ]]; then
        log "git命令不存在，请安装git客户端"
        exit 1;
    fi
}

log ""
log "==================== 脚本执行开始 ===================="

case $1 in
"release")
    release
    ;;

"comparison")
    valid
    comparison
    ;;

"upgrade")
    valid
    upgrade
    ;;

"clear")
    clear
    echo "临时文件清理完成"
    ;;

*)
    echo "========== Anvil平台前端代码管理客户端工具 =========="
    echo ""
    echo "使用方式 sh anvil-cli.sh [OPTION]"
    echo "windows环境使用前请先关闭git的自动转换换行符功能，具体执行命令为："
    echo "git config --global core.autocrlf false"
    echo ""
    echo "[OPTION]支持的选项:"
    echo "  release:    发布项目的文件指纹"
    echo "  comparison: 比对当前项目跟目标版本的项目文件差异"
    echo "  upgrade:    比对当前项目跟目标版本的项目文件差异，并进行处理"
    echo "  clear:      清理临时文件"
    echo ""
    echo "例如:"
    echo "     sh anvil-cli.sh release    发布项目的文件指纹"
    echo "     sh anvil-cli.sh comparison 比对当前项目跟目标版本的项目文件差异"
    echo "     sh anvil-cli.sh upgrade    比对当前项目跟目标版本的项目文件差异，并进行处理"
    echo "     sh anvil-cli.sh clear      清理临时文件"
    echo "==================================================="
    ;;
esac

if [[ $1 != "clear" ]]; then
    log "==================== 脚本执行结束 ===================="
fi
